/*
 * Created by Spear (http://www.codernet.es), spear@codernet.es
 * Coordinator of XNA Community (http://www.codeplex.com/XNACommunity)
 * 
 */

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Content.Pipeline;

namespace XMasContent
{
    public class Cal3DSkeletonParser
    {
        // -----------------------------------------------------------------
        public struct TNode 
        {
            public int          id;           // Sequence order in the skeleton
            public string       name;         // Name of this bone
            public int          parent_id;    // Parent node, or null if root node
            public List<int>    childrens;    // This node is not the owner of these children
            public Vector3 position;
            public Quaternion orientation;
        };

        public struct TCalBone 
        {
            public Vector3 local;
            public Quaternion local_rot;
            public Vector3 bone_space_translate;    // Not used
            public Quaternion bone_space_rotation;
	        public int parent_id;
	        public int nchildren;
        };
        public List<TNode> list_nodes = new List<TNode>();


        bool isValid(char[] magic)
        {
            return (magic[0] == 'C' && magic[1] == 'S' && magic[2] == 'F' && magic[3] == 0x00);
        }
   
    
        void loadNode(BinaryReader reader)
        {
            TNode node = new TNode();
            node.childrens = new List<int>();
            node.name = XmasContent.GetInstance().readString(reader);
            node.id = list_nodes.Count;
            TCalBone cal_bone;
            cal_bone.local = XmasContent.GetInstance().readVector3(reader);
            cal_bone.local_rot = XmasContent.GetInstance().readQuaternion(reader);
            cal_bone.bone_space_translate = XmasContent.GetInstance().readVector3(reader);
            cal_bone.bone_space_rotation = XmasContent.GetInstance().readQuaternion(reader);
	        cal_bone.parent_id = reader.ReadInt32();
            cal_bone.nchildren = reader.ReadInt32();

            // Save bone_space transform in the bind transform 
            //node.position = cal_bone.bone_space_translate;
            //node.orientation = Quaternion.Inverse(cal_bone.bone_space_rotation);
            // We don't want inverse bind pose, we want pose
            node.position = cal_bone.local;
            node.orientation = Quaternion.Inverse(cal_bone.local_rot);
            

            node.parent_id = cal_bone.parent_id;

            for (int i = 0; i < cal_bone.nchildren; ++i)
            {
                int child_id = reader.ReadInt32();
                node.childrens.Add(child_id);
            }

            list_nodes.Add(node);
        }


        public void load(string filename, ContentImporterContext context)
        {
            XmasContent.GetInstance().SetContextImporter(context);
            FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read);
            BinaryReader reader = new BinaryReader(file);
            char[] magic = new char[4];
            magic = reader.ReadChars(4);
            if (isValid(magic))
            {
                reader.ReadInt32();
                int bones_count = reader.ReadInt32();
                for (int i = 0; i < bones_count; ++i)
                {
                    loadNode(reader);
                }
            }
            else
            {
                throw new ArgumentNullException("File: " + filename + ", CMF Version not supported.\n");
            }

            reader.Close();
        }
    } 
}
